package com.workflow.workflowproject.pojo.node;

import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.workflow.workflowproject.mapper.FlowNodeApproveMapper;
import com.workflow.workflowproject.mapper.FlowNodeFieldMapper;
import com.workflow.workflowproject.mapper.FlowNodeOptionMapper;
import com.workflow.workflowproject.pojo.FormOperation;
import com.workflow.workflowproject.pojo.enums.ApprovalMultiEnum;
import com.workflow.workflowproject.pojo.enums.ApprovalNobodyEnum;
import com.workflow.workflowproject.pojo.lowflow.FlowNodeApprove;
import com.workflow.workflowproject.pojo.lowflow.FlowNodeField;
import com.workflow.workflowproject.pojo.lowflow.FlowNodeOption;
import com.workflow.workflowproject.pojo.lowflow.table.FlowNodeFieldTableDef;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description：审批节点
 */
@EqualsAndHashCode(callSuper = true)
@Data
@Component
public class ApprovalNode extends AssigneeNode {

    @Autowired
    private FlowNodeApproveMapper flowNodeApproveMapper;
    @Autowired
    private FlowNodeOptionMapper flowNodeOptionMapper;
    @Autowired
    private FlowNodeFieldMapper flowNodeFieldMapper;

    private static ApprovalNode approvalNode;

    @PostConstruct
    public void init(){
        approvalNode = this;
        approvalNode.flowNodeApproveMapper = this.flowNodeApproveMapper;
        approvalNode.flowNodeOptionMapper = this.flowNodeOptionMapper;
        approvalNode.flowNodeFieldMapper = this.flowNodeFieldMapper;
    }

    // 表单属性
    private List<FormOperation> formProperties = new ArrayList<>();
    // 操作权限
    private Map<String, Boolean> operations = new LinkedHashMap<>();
    // 多人审批方式
    private ApprovalMultiEnum multi;
    // 多人会签通过百分比
    private BigDecimal multiPercent;
    // 审批人为空时处理方式
    private ApprovalNobodyEnum nobody;
    // 审批人为空时指定人员
    private List<String> nobodyUsers;
    // 任务监听器
    private List<NodeListener> taskListeners;

    @Override
    public List<FlowElement> convert() {
        //----------保存审批人员控制---------------//
        FlowNodeApprove flowNodeApprove = approvalNode.flowNodeApproveMapper.selectOneById(this.getId());
        //如果该任务的审批人员不存在，则新增
        if(ObjectUtil.isEmpty(flowNodeApprove)){
            flowNodeApprove = new FlowNodeApprove();
            //将参数拷贝进审批人员数据中
            BeanUtils.copyProperties(this,flowNodeApprove);
            flowNodeApprove.setId(this.getId());
            flowNodeApprove.setMulti(multi.getMulti());
            flowNodeApprove.setMultiPercent(multiPercent.doubleValue());
            flowNodeApprove.setNobody(nobody.getNobody());
            flowNodeApprove.setNobodyUsers(nobodyUsers);
            approvalNode.flowNodeApproveMapper.insert(flowNodeApprove);
        }else{
            //如果该任务的审批人员存在，则更新
            BeanUtils.copyProperties(this,flowNodeApprove);
            flowNodeApprove.setMulti(multi.getMulti());
            flowNodeApprove.setMultiPercent(multiPercent.doubleValue());
            flowNodeApprove.setNobody(nobody.getNobody());
            flowNodeApprove.setNobodyUsers(nobodyUsers);
            approvalNode.flowNodeApproveMapper.update(flowNodeApprove);
        }
        //----------保存节点审批控制------------------//
        FlowNodeOption flowNodeOption = approvalNode.flowNodeOptionMapper.selectOneById(this.getId());
        if(ObjectUtil.isEmpty(flowNodeOption)){
            flowNodeOption = new FlowNodeOption();
            //如果保存节点审批控制不存在，则新增
            flowNodeOption.setId(this.getId());
            flowNodeOption.setAgree(operations.get("complete")?1:0);//是否同意（0、不可操作；1、可操作）
            flowNodeOption.setRefuse(operations.get("refuse")?1:0);//是否拒绝（0、不可操作；1、可操作）
            flowNodeOption.setReturnData(operations.get("back")?1:0);//是否退回（0、不可操作；1、可操作）
            flowNodeOption.setTransmit(operations.get("transfer")?1:0);//是否转交（0、不可操作；1、可操作）
            flowNodeOption.setDelegate(operations.get("delegate")?1:0);//是否委派（0、不可操作；1、可操作）
            flowNodeOption.setCountersign(operations.get("addMulti")?1:0);//是否加签（0、不可操作；1、可操作）
            flowNodeOption.setReduceVisa(operations.get("minusMulti")?1:0);//是否减签（0、不可操作；1、可操作）
            approvalNode.flowNodeOptionMapper.insert(flowNodeOption);
        }else{
            //如果保存节点审批控制不存在，则修改
            flowNodeOption.setAgree(operations.get("complete")?1:0);//是否同意（0、不可操作；1、可操作）
            flowNodeOption.setRefuse(operations.get("refuse")?1:0);//是否拒绝（0、不可操作；1、可操作）
            flowNodeOption.setReturnData(operations.get("back")?1:0);//是否退回（0、不可操作；1、可操作）
            flowNodeOption.setTransmit(operations.get("transfer")?1:0);//是否转交（0、不可操作；1、可操作）
            flowNodeOption.setDelegate(operations.get("delegate")?1:0);//是否委派（0、不可操作；1、可操作）
            flowNodeOption.setCountersign(operations.get("addMulti")?1:0);//是否加签（0、不可操作；1、可操作）
            flowNodeOption.setReduceVisa(operations.get("minusMulti")?1:0);//是否减签（0、不可操作；1、可操作）
            approvalNode.flowNodeOptionMapper.update(flowNodeOption);
        }
        //----------节点表单控制------------------//
        for(FormOperation oFormProperty : formProperties){
            if(oFormProperty.getHidden() != null && oFormProperty.getRequired() != null && oFormProperty.getReadonly() != null){
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.where(FlowNodeFieldTableDef.FLOW_NODE_FIELD.FIELD_ID.eq(oFormProperty.getId()));
                queryWrapper.where(FlowNodeFieldTableDef.FLOW_NODE_FIELD.TASK_NODE_ID.eq(this.getId()));
                FlowNodeField flowNodeField = approvalNode.flowNodeFieldMapper.selectOneByQuery(queryWrapper);
                if(ObjectUtil.isEmpty(flowNodeField)){
                    flowNodeField = new FlowNodeField();
                    flowNodeField.setFieldId(oFormProperty.getId());
                    flowNodeField.setTaskNodeId(this.getId());
                    flowNodeField.setRequired(oFormProperty.getRequired()?1:0);
                    flowNodeField.setHidden(oFormProperty.getHidden()?1:0);
                    flowNodeField.setReadable(oFormProperty.getReadonly()?1:0);
                    approvalNode.flowNodeFieldMapper.insert(flowNodeField);
                }else{
                    flowNodeField.setRequired(oFormProperty.getRequired()?1:0);
                    flowNodeField.setHidden(oFormProperty.getHidden()?1:0);
                    flowNodeField.setReadable(oFormProperty.getReadonly()?1:0);
                    approvalNode.flowNodeFieldMapper.update(flowNodeField);
                }
            }
        }
        ArrayList<FlowElement> elements = new ArrayList<>();
        // 用户节点
        UserTask userTask = new UserTask();
        userTask.setId(this.getId());
        userTask.setName(this.getName());
        // userTask.setAsynchronous(true);
        // userTask.setFormKey(this.getFormKey());
        userTask.setExecutionListeners(this.buidEventListener());
        //添加流程结束监听，给下一个节点任务创建任务人
        List<FlowableListener> listeners = new ArrayList<>();
        if (!CollectionUtils.isEmpty(this.taskListeners)) {
            listeners = this.taskListeners.stream().filter(l -> StringUtils.isNotBlank(l.getImplementation())).map(listener -> {
                FlowableListener eventListener = new FlowableListener();
                eventListener.setEvent(listener.getEvent());
                eventListener.setImplementation(listener.getImplementation());
                eventListener.setImplementationType(listener.getImplementationType());
                return eventListener;
            }).collect(Collectors.toList());
        }
        userTask.setTaskListeners(listeners);
        // 审批人
        MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics();
        if (this.getMulti() == ApprovalMultiEnum.SEQUENTIAL) {
            multiInstanceLoopCharacteristics.setSequential(true);
        } else if (this.getMulti() == ApprovalMultiEnum.JOINT) {
            multiInstanceLoopCharacteristics.setSequential(false);
            if (Objects.nonNull(this.getMultiPercent()) && this.getMultiPercent().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal percent = this.getMultiPercent().divide(new BigDecimal(100), 2, RoundingMode.DOWN);
                multiInstanceLoopCharacteristics.setCompletionCondition(String.format("${nrOfCompletedInstances/nrOfInstances >= %s}", percent));
            }
        } else if (this.getMulti() == ApprovalMultiEnum.SINGLE) {
            multiInstanceLoopCharacteristics.setSequential(false);
            multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances > 0}");
        }
//        String variable = String.format("%sItem", this.getId());
//        multiInstanceLoopCharacteristics.setElementVariable(variable);
//        multiInstanceLoopCharacteristics.setInputDataItem(String.format("${%sCollection}", this.getId()));
//        userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
//        userTask.setAssignee(String.format("${%s}", variable));
        multiInstanceLoopCharacteristics.setElementVariable("${Item}");
        multiInstanceLoopCharacteristics.setInputDataItem("${Collection}");
        userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
        userTask.setAssignee("${Item}");
        elements.add(userTask);
        // 下一个节点的连线
        Node child = this.getChild();
        SequenceFlow sequenceFlow = this.buildSequence(child);
        elements.add(sequenceFlow);
        // 下一个节点
        if (Objects.nonNull(child)) {
            child.setBranchId(this.getBranchId());
            List<FlowElement> flowElements = child.convert();
            elements.addAll(flowElements);
        }
        return elements;
    }

}
